<template>
  <div class="scroll-num-container" :style="`height: ${height}px`">
    <ul v-if="type && type.indexOf('random') !== -1">
      <li v-for="(char, index) in randomNum" :key="index" class="num-item" :style="fontStyle">
        <span v-if="!isNaN(Number(char))">
          <h4 ref="numItem">0123456789</h4>
        </span>
        <h4 v-else>{{ char }}</h4>
      </li>
    </ul>
    <ul v-else>
      <li v-for="(char, index) in computedNum" :key="index" class="num-item" :style="fontStyle">
        <span v-if="!isNaN(Number(char))">
          <h4 ref="numItem">0123456789</h4>
        </span>
        <h4 v-else>{{ char }}</h4>
      </li>
    </ul>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import { Component, Prop, Watch, Ref } from 'vue-property-decorator'
import { Dictionary } from 'vue-router/types/router'
@Component
class ScrollNum extends Vue {
  @Ref() numItem!: HTMLElement[]
  @Prop({ default: 0 }) num!: number
  @Prop({ default: 35 }) height!: number
  @Prop({ default: 'normal' }) type!: string
  @Prop({ default: () => ({}) }) fontStyle!: Dictionary<string>
  interval: NodeJS.Timeout | null = null
  randomNum: string[] = ['0', '0', '0']
  get computedNum() {
    const numArr = this.num.toFixed().split('')
    let splitCharIdx = numArr.length - 3
    while (splitCharIdx > 0) {
      numArr.splice(splitCharIdx, 0, ',')
      splitCharIdx -= 3
    }
    return numArr
  }
  @Watch('computedNum', { deep: true })
  cn_handler(newVal: string[]) {
    this.setNumTransform(newVal)
  }
  @Watch('type', { immediate: true })
  type_handler() {
    if (!this.type) return
    if (this.type.indexOf('random') !== -1) {
      if (this.interval) clearInterval(this.interval)
      this.interval = setInterval(() => {
        const numArr = (Math.random() * 1000).toFixed().split('')
        let splitCharIdx = numArr.length - 3
        while (splitCharIdx > 0) {
          numArr.splice(splitCharIdx, 0, ',')
          splitCharIdx -= 3
        }
        this.randomNum = numArr
        this.setNumTransform(numArr)
      }, 10 * 1000)
    }
  }
  mounted() {
    this.setNumTransform()
  }
  beforeDestroy() {
    if (this.interval) clearInterval(this.interval)
  }
  setNumTransform(numArr?: string[]) {
    this.$nextTick(() => {
      // 数字节点
      const numItems = this.numItem
      if (!numItems) return
      // 每个节点对应的值
      const targetArr = !numArr ? this.computedNum : numArr
      const numberArr = targetArr.filter(item => item !== ',').map(char => Number(char))
      for (let i = 0; i < numItems.length; i++) {
        const curItem = numItems[i]
        curItem.animate(
          [
            { transform: 'translate(-50%, 0)' },
            { transform: `translate(-50%, -${numberArr[i] * 10}%)` }
          ],
          { duration: 1000 - 200 * i, easing: 'ease', fill: 'both' }
        )
      }
    })
  }
}
export default ScrollNum
</script>

<style lang="less" scoped>
@import '~@/styles/theme.less';
@import '~@/styles/layout.less';
.scroll-num-container {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  ul {
    margin-block: 0;
    padding: 0;
    list-style: none;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    .num-item {
      display: inline-block;
      width: 15px;
      height: 100%;
      font-size: 24px;
      font-weight: 900;
      #color(color, --primary-text-color);
      h4 {
        margin-block: 0;
      }
      span {
        position: relative;
        display: inline-block;
        width: 100%;
        height: 100%;
        text-align: center;
        writing-mode: vertical-rl;
        text-orientation: upright;
        overflow: hidden;
        h4 {
          position: absolute;
          top: 15%;
          left: 50%;
          font-size: inherit;
          font-weight: inherit;
          transform: translate(-50%, 0);
          transition: transform 0.5s ease-in-out;
          letter-spacing: 10px;
        }
      }
    }
  }
}
</style>
